<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>lazy-seq</title>
</head>
<body>
	<script>
	function identity(a){
		return a
	}
	function cons(a,b){
		if(typeof b !=="function")throw "arg 2 must is function";
		function r(flg){			
			return {head:a,tail:b}[flg];
		}
		r.toString=function(){
			return "lazy-seq:"+formatCacheValue(r,200);
		}
		return r;
	}
	function head(lis){
		return lis("head");
	}
	function tail(lis){
		if(lis.cacheValue)return lis.cacheValue;
		lis.cacheValue=lis("tail")(lis);
		return lis.cacheValue;
	}
	function isEmptyLs(ls){
		return ls===null;
	}
	function formatCacheValue(ls,deep){
		if(isEmptyLs(ls))return "nil";
		if(ls.cacheValue===undefined)return head(ls)+"->wating...";
		if(deep==0)return "..."
		return head(ls)+"->"+formatCacheValue(ls.cacheValue,deep-1);
	}
	function take(n,ls){
		if(n<0) throw "arg 1 must >0";
		if(n==0)return [];
		if(isEmptyLs(ls))return [];
		if(n==1)return [head(ls)];
		return [head(ls)].concat(take(n-1,tail(ls)));
	}
	function nth(idx,ls){
		if(idx==0)return head(ls);
		return nth(idx-1,tail(ls));
	}
	function map(fn){
		return function(ls){
			return cons(fn(head(ls)),map(fn));
		}
	}
	function map2(fn){
		return function(ls1){
			return function(ls2){
				return cons(fn(head(ls1))(head(ls2)),map2(fn)(ls2));
			}
		}
	}
	function add(a){
		return function(b){
			return a+b;
		}
	}

	function filter(fn){
		return function(ls){
			if(isEmptyLs(ls))return null;
			var val=head(ls);
			if(fn(val))return cons(val,function(){
				return filter(fn)(tail(ls));
			});
			return filter(fn)(tail(ls));
		}
	}
	function create10seq(seq){
		if(head(seq)==10)return null;
		return cons(head(seq)+1,create10seq);
	}
	//1 2 3 4 5 6 7 8 9 10
	var l10=cons(1,create10seq);
	//1,1,1,1.....
	var l1=cons(1,identity);
	//1,2,3,4,5,6,7,8.....
	var l2=cons(1,map(add(1)));
	//0,1,1,2,3,5,8.....
	var fib=cons(0,function(seq){
		return cons(1,map2(add)(seq));
	})
	//take(10,filter(function(a){return a>100})(fib))

	//性能对比
	function fibfn(n){
		if(n==0)return 0;
		if(n==1)return 1;
		return fibfn(n-2)+fibfn(n-1);
	}
	//由于fibfn传入50浏览器就卡死了拿小点的做比较吧
	console.time("fibfn");
	console.log(fibfn(40));
	console.timeEnd("fibfn");

	console.time("lazy-seq-fib");
	console.log(nth(40,fib));
	console.timeEnd("lazy-seq-fib");
	</script>
</body>
</html>